﻿#include "outputpdf.h"

#include <QDebug>

//#pragma execution_character_set("utf-8")
/**
 * @class OutputPDF
 * @brief 用于生成PDF文档的类，支持文本和图片输出
 */

/**
 * @brief 构造函数，初始化PDF文档生成器
 * @param path PDF文档保存路径
 * @param path_pixmap 图片PDF保存路径
 */
OutputPDF::OutputPDF(const QString &path, const QString &path_pixmap) :
    m_filepath(std::move(path)),
    m_filepath_pixmap(std::move(path_pixmap)),
    m_tablen(0),
    m_rowheight(400),
    m_rowcnt(0)
{
    m_pdfwrite = new QPdfWriter(m_filepath);                //实例化QPdfWriter
    m_pdfwrite->setPageSize(QPagedPaintDevice::A4);         //设置纸张为A4纸
    m_pdfwrite->setResolution(QPrinter::ScreenResolution);  //设置分辨率
    m_pdfwrite->setPageMargins(QMarginsF(40, 40, 40, 40));  //设置页边距 顺序是:左上右下

    m_pdfwrite_pixmap = new QPdfWriter(m_filepath_pixmap);         //实例化QPdfWriter
    m_pdfwrite_pixmap->setPageSize(QPagedPaintDevice::A4);         //设置纸张为A4纸
    m_pdfwrite_pixmap->setResolution(QPrinter::ScreenResolution);  //设置分辨率
    m_pdfwrite_pixmap->setPageMargins(QMarginsF(40, 40, 40, 40));  //设置页边距 顺序是:左上右下

    m_pdfpainter = new QPainter(m_pdfwrite);
    m_pdfpainter_pixmap = new QPainter(m_pdfwrite_pixmap);

    m_textoption = new QTextOption(Qt::AlignCenter);    //居中显示
    this->SetTextOption(Qt::AlignCenter, QTextOption::WordWrap);

    m_font = new QFont();
    SetTextFont("Microsoft YaHei", 20, true, false,false);
}

/**
 * @brief 析构函数，释放资源
 */
OutputPDF::~OutputPDF()
{
    delete m_font;
    delete m_textoption;
    delete m_pdfpainter;
    delete m_pdfwrite;
    delete m_pdfpainter_pixmap;
    delete m_pdfwrite_pixmap;
}

/**
 * @brief 将图片保存到PDF文档
 * @param pixmap 要保存的图片列表
 * @param pixx 图片在PDF中的X坐标
 * @param pixy 图片在PDF中的Y坐标
 */
void OutputPDF::SavePixmapToPDF(const QVector<QPixmap> &pixmap, const int pixx, const int pixy)
{
    /******************************************************以下为自定义绘图**************************************/
    QFile pdfFile(m_filepath_pixmap);//输出文件名
    if(!pdfFile.open(QIODevice::WriteOnly))
    {
        qDebug() << QString("Cannot open file:\n%1").arg(m_filepath_pixmap);
        return;
    }
    if(pixmap.size() == 0)
    {
        qDebug() << "没有图片数据";
        return;
    }

    //    QRect rect = m_pdfpainter_pixmap->viewport();
    //    int scale = rect.width()/pixmap.at(0).width();
    for(int i = 0; i < pixmap.size(); ++i)
    {
        if(pixmap[i].isNull())
            continue;
        QPixmap scaledPixmap = std::move(pixmap[i].scaled(7500, 6400, Qt::KeepAspectRatio));
        //m_pdfpainter_pixmap->scale(scale, scale);        //图像缩放 不然图片太大或者太小都不好看
        m_pdfpainter_pixmap->drawPixmap(pixx, pixy, scaledPixmap);  //画图
        m_pdfwrite_pixmap->newPage();
    }
    m_pdfpainter_pixmap->end();

    pdfFile.close();
}

/**
 * @brief 将文本数据保存到PDF文档
 * @param context 要保存的文本内容
 */
void OutputPDF::SaveDataToPDF(const QString &context)
{
    QFile pdfFile(m_filepath);//输出文件名
    if(!pdfFile.open(QIODevice::WriteOnly))
    {
        qDebug() << QString("Cannot open file:\n%1").arg(m_filepath);
        return;
    }

    //距离左边m_tablen,上面m_rowcnt*m_rowheight+40,
    //标题字宽度8000，标题字高m_rowheight（如果字显示不全，可以适当调整）
    m_pdfpainter->drawText(std::move(QRect(m_tablen, m_rowcnt*m_rowheight+40, 8000, m_rowheight)), context, *m_textoption);
    ++m_rowcnt;

    pdfFile.close();

    //    m_pdfpainter->drawText(QRect(500, 20, 8000, 300),
    //                           QString::fromLocal8Bit("我是第一行我是第一行"));
    //    m_pdfpainter->drawText(QRect(0, 320, 8500, 300),
    //                           QString::fromLocal8Bit("我是后续我是后"), *m_textoption);
    //    m_pdfpainter->drawText(QRect(0, 620, 8500, 300),
    //                           QString::fromLocal8Bit("我是后续我是后续"), *m_textoption);

}

/**
 * @brief 设置文本对齐模式和换行模式
 * @param align 文本对齐方式
 * @param wrapmode 文本换行模式
 */
void OutputPDF::SetTextOption(const Qt::AlignmentFlag align, const QTextOption::WrapMode wrapmode)
{
    m_textoption->setAlignment(align);
    m_textoption->setWrapMode(wrapmode);
}

/**
 * @brief 设置文本字体样式
 * @param family 字体名称
 * @param size 字体大小
 * @param isbold 是否加粗
 * @param isitalic 是否斜体
 * @param isunderline 是否有下划线
 */
void OutputPDF::SetTextFont(const QString &family, const int size, const bool isbold, const bool isitalic, const bool isunderline)
{
    m_font->setFamily(family);           //设置字体 微软雅黑、宋体之类的
    m_font->setPointSize(size);          //设置字体大小
    m_font->setItalic(isitalic);         //斜体
    m_font->setUnderline(isunderline);   //设置下划线
    m_font->setBold(isbold);             //加粗
    m_pdfpainter->setFont(*m_font);
}

/**
 * @class PdfAPI
 * @brief 提供PDF生成的API接口，支持表格和图片输出
 */

// 静态成员变量初始化
PdfAPI *PdfAPI::_instance = 0;

/**
 * @brief 构造函数
 * @param parent 父对象
 */
PdfAPI::PdfAPI(QObject *parent) : QObject(parent)
{
}

/**
 * @brief 保存表格数据到PDF
 * @param fileName 输出文件名
 * @param title 表格标题
 * @param subTitle 表格副标题
 * @param columnNames 列名列表
 * @param columnWidths 列宽列表
 * @param content 表格内容
 * @param landscape 是否横向打印
 * @param check 是否检查历史记录（历史记录显示为红色）
 * @param pageSize 纸张大小
 */
void PdfAPI::SavePdf(QString fileName, QString title, QString subTitle, QList<QString> columnNames,
                     QList<int> columnWidths, QStringList content, bool landscape, bool check,
                     QPrinter::PageSize pageSize)
{
    //计算行数列数
    int columnCount = columnNames.count();
    int rowCount = content.count();

    //清空原有数据,确保每次都是新的数据
    html.clear();

    //表格开始
    html.append("<table border='0.5' cellspacing='0' cellpadding='3'>");

    //标题占一行,居中显示
    if (title.length() > 0) {
        html.append(QString("<tr><td align='center' style='vertical-align:middle;font-weight:bold;' colspan='%1'>")
                    .arg(columnCount));
        html.append(title);
        html.append("</td></tr>");
    }

    //副标题占一行,左对齐显示
    if (subTitle.length() > 0) {
        html.append(QString("<tr><td align='left' style='vertical-align:middle;' colspan='%1'>")
                    .arg(columnCount));
        html.append(subTitle);
        html.append("</td></tr>");
    }

    //循环写入字段名,字段名占一行,居中显示
    if (columnCount > 0) {
        html.append("<tr>");
        for (int i = 0; i < columnCount; i++) {
            html.append(QString("<td width='%1' bgcolor='lightgray' align='center' style='vertical-align:middle;'>")
                        .arg(columnWidths.at(i)));
            html.append(columnNames.at(i));
            html.append("</td>");
        }
        html.append("</tr>");
    }

    //循环一行行构建数据
    for (int i = 0; i < rowCount; i++) {
        QStringList value = content.at(i).split(";");
        html.append("<tr>");

        if (check) {
            if (value.at(value.count() - 1) == "历史记录") {
                for (int j = 0; j < columnCount; j++) {
                    html.append(QString("<td width='%1' align='center' style='vertical-align:middle;'>"
                                        "<font color='red'>").arg(columnWidths.at(j)));
                    html.append(value.at(j));
                    html.append("</font></td>");
                }
            } else {
                for (int j = 0; j < columnCount; j++) {
                    html.append(QString("<td width='%1' align='center' style='vertical-align:middle;'>")
                                .arg(columnWidths.at(j)));
                    html.append(value.at(j));
                    html.append("</td>");
                }
            }
        } else {
            for (int j = 0; j < columnCount; j++) {
                html.append(QString("<td width='%1' align='center' style='vertical-align:middle;'>")
                            .arg(columnWidths.at(j)));
                html.append(value.at(j));
                html.append("</td>");
            }
        }

        html.append("</tr>");
    }

    html.append("</table>");

    //调用打印机打印PDF
    QPrinter printer;
    //设置纸张规格
    printer.setPageSize(pageSize);
    //设置横向纵向及页边距
    if (landscape) {
        //Orientation：纸张方向，有QPrinter::Portrait(纵向)和QPrinter::Landscape(横向)
        printer.setOrientation(QPrinter::Landscape);
        printer.setPageMargins(10, 10, 10, 11, QPrinter::Millimeter);
    } else {
        printer.setOrientation(QPrinter::Portrait);
        printer.setPageMargins(10, 10, 10, 15, QPrinter::Millimeter);
    }
    //设置输出格式为PDF
    printer.setOutputFormat(QPrinter::PdfFormat);
    //设置输出文件保存位置
    printer.setOutputFileName(fileName);

    QTextDocument textDocument;
    textDocument.setHtml(html.join(""));
    textDocument.print(&printer);
    textDocument.end();
}

/**
 * @brief 保存复杂数据到PDF（支持多级标题）
 * @param fileName 输出文件名
 * @param title 表格标题
 * @param columnNames 列名列表
 * @param columnWidths 列宽列表
 * @param subTitle1 第一级副标题列表
 * @param subTitle2 第二级副标题列表
 * @param content 表格内容
 * @param landscape 是否横向打印
 * @param check 是否检查历史记录（历史记录显示为红色）
 * @param pageSize 纸张大小
 */
void PdfAPI::SavePdf(QString fileName, QString title, QList<QString> columnNames,
                     QList<int> columnWidths, QStringList subTitle1, QStringList subTitle2,
                     QStringList content, bool landscape, bool check, QPrinter::PageSize pageSize)
{
    //计算列数
    int columnCount = columnNames.count();

    //清空原有数据,确保每次都是新的数据
    html.clear();

    //表格开始
    html.append("<table border='0.5' cellspacing='0' cellpadding='3'>");

    //标题占一行,居中显示
    if (title.length() > 0) {
        html.append(QString("<tr><td align='center' style='vertical-align:middle;font-weight:bold;' colspan='%1'>")
                    .arg(columnCount));
        html.append(title);
        html.append("</td></tr>");
    }

    //循环添加副标题/字段名/内容
    int count = content.count();
    for (int i = 0; i < count; i++) {
        //加个空行隔开
        html.append(QString("<tr><td colspan='%1'>").arg(columnCount));
        html.append("</td></tr>");

        //副标题1
        if (subTitle1.count() > 0 && subTitle1.count() > i) {
            if (subTitle1.at(i).length() > 0) {
                html.append(QString("<tr><td align='left' style='vertical-align:middle;' colspan='%1'>")
                            .arg(columnCount));
                html.append(subTitle1.at(i));
                html.append("</td></tr>");
            }
        }

        //副标题2
        if (subTitle2.count() > 0 && subTitle2.count() > i) {
            if (subTitle2.at(i).length() > 0) {
                html.append(QString("<tr><td align='left' style='vertical-align:middle;' colspan='%1'>")
                            .arg(columnCount));
                html.append(subTitle2.at(i));
                html.append("</td></tr>");
            }
        }

        //逐个添加字段名称
        if (columnCount > 0) {
            html.append("<tr>");
            for (int i = 0; i < columnCount; i++) {
                html.append(QString("<td width='%1' bgcolor='lightgray' align='center' style='vertical-align:middle;'>")
                            .arg(columnWidths.at(i)));
                html.append(columnNames.at(i));
                html.append("</td>");
            }
            html.append("</tr>");
        }

        QStringList list = content.at(i).split(";");

        //逐个添加数据
        int rowCount = list.count();
        for (int j = 0; j < rowCount; j++) {
            html.append("<tr>");

            QString temp = list.at(j);
            QStringList value = temp.split("|");
            int valueCount = value.count();

            if (check) {
                //如果是历史记录则文字红色
                if (value.at(valueCount - 1) == "1") {
                    for (int k = 0; k < valueCount - 1; k++) {
                        html.append(QString("<td width='%1' align='center' style='vertical-align:middle;'>"
                                            "<font color='red'>").arg(columnWidths.at(k)));
                        html.append(value.at(k));
                        html.append("</font></td>");
                    }
                } else {
                    for (int k = 0; k < valueCount - 1; k++) {
                        html.append(QString("<td width='%1' align='center' style='vertical-align:middle;'>")
                                    .arg(columnWidths.at(k)));
                        html.append(value.at(k));
                        html.append("</td>");
                    }
                }
            } else {
                for (int k = 0; k < valueCount; k++) {
                    html.append(QString("<td width='%1' align='center' style='vertical-align:middle;'>")
                                .arg(columnWidths.at(k)));
                    html.append(value.at(k));
                    html.append("</td>");
                }
            }

            html.append("</tr>");
        }
    }

    html.append("</table>");

    //调用打印机打印PDF
    QPrinter printer;
    //设置纸张规格
    printer.setPageSize(pageSize);
    //设置横向纵向及页边距
    if (landscape) {
        printer.setOrientation(QPrinter::Landscape);
        printer.setPageMargins(10, 10, 10, 11, QPrinter::Millimeter);
    } else {
        printer.setOrientation(QPrinter::Portrait);
        printer.setPageMargins(10, 10, 10, 15, QPrinter::Millimeter);
    }
    //设置输出格式为PDF
    printer.setOutputFormat(QPrinter::PdfFormat);
    //设置输出文件保存位置
    printer.setOutputFileName(fileName);

    QTextDocument textDocument;
    textDocument.setHtml(html.join(""));
    textDocument.print(&printer);
    textDocument.end();
}



